/**
 * \file
 *          teleStarterThread.cpp
 * \brief
 *          Implements starter thread of entTelematics
 *
 * \par Author (last changes):
 *          - Tie Jim Seng
 *          - Phone +65 67799 740
 *          - Continental Automotive GmbH
 * \par Project Leader:
 *          - Mandy Sin
 *          - Phone +65 67799 819
 *          - Mandy.Sin@continental-corporation.com
 * \par Responsible Developer:
 *          - Tie Jim Seng
 *          - Phone +65 67799 740
 *          - Continental Automotive GmbH
 * \par Responsible Architect:
 *          - Goh Hoe Chun
 *          - Phone +65 67799 586
 *          - Hoe.Chun.Goh@continental-corporation.com
 *
 * \par Project:
 *      DPCA B73 Navi
 *
 * \par SW-Component:
 *      entTelematics
 *
 * \par SW-Package:
 *      Telematics Main
 *
 * \par SW-Module:
 *      Telematics Main
 *
 * \par SW-Architecture Specification:
 *      DPCA_SW_AD_IMX
 *      003
 *
 * \par SW-Design Specification:
 *      DPCA_your_module_SW_DD
 *      your_doc_number
 *
 * \par SW-Test Case Specification:
 *      DPCA_your_module_SW_TS
 *      your_doc_number
 *
 * \par CM-Info:
 *      - teleStarterThread.cpp-1:c++:DPCARSgp#1
 *      - uidc0931
 *
 * \note
 *      This is a note.
 *
 * \bug
 *      - there are no known bugs
 *
 * \par Module-History:
 *
 * \verbatim
 * Date                     Author                     Reason
 * 20 Dec 2011        Song Yang                     Initial Creation
 * The latest entry at the head of the history list.
 * \endverbatim
 *
 * \par Copyright Notice:
 * Copyright (C) 2011 Continental Automotive Singapore Pte Ltd.
 * Alle Rechte vorbehalten. All Rights Reserved.\n
 * The reproduction, transmission or use of this document or its contents is
 * not permitted without express written authority.\n
 * Offenders will be liable for damages. All rights, including rights created
 * by patent grant or registration of a utility model or design, are reserved.
 *
 */

#include "HiGraphQueue.h"

#include "RPCAsyncDescriptor.h"
#include "SystemConf.h"
#include "teleLogTrace.h"

#include "teleStarterThread.h"
#include "teleMainBLthread.h"
#include "teleMainAppthread.h"
#include "teleMQTTClientAdapter.h"
#include "entITeleUMSGQ_def.h"

#include "entITelematics.h"
#include "ConnMgrBLThread.h"
#include "ConnMgrStateEvt.h"
#include "tlmPushObjStateEvt.h"
#include "tlmUrlBackStateEvt.h"
#include "tlmRmtCfgSrvThread.h"

#include "HiGraphTeleAudioBLEvent.h"
#include "Tlm_MostStack.h"
#include "midTlmAudioLogicalSource.h"

#include "RmtCfgStateEvt.h"

#include "ssw_IEmbRegistry.h"
#include "app_IEmbRegistryIDs.h"

extern HiGraphQueue gTeleQueue;
extern HiGraphQueue gConnMgrQueue;

uint8_t teleStarterThread::mVBUSOnoff;
uint8_t teleStarterThread::mVBUSPort;

/**
* @brief This function is a constructor of stater thread class used in the entTelematics process
*
* @return - none
*
* @note
*/
teleStarterThread::teleStarterThread()
:StarterThread(ENTTELEMATICS_STARTER_THREAD,ENTTELEMATICS_STARTER_THREAD_PRORITY, ENTTELEMATICS_STARTER_STACK_SIZE,entTotalProcess,entTelematics),
mpTlmBLthread(0),
mpTlmAppthread(0),
mpConnMgrBLThread(0),
mpRmtCfgSrvThread(0),
mpTlmMostReceiverThread(0),
mpUsbDiagBLThread(0)
{
  LOG_PRINT(DPCA_TELE_MAIN_INFO,"[TELEMAIN]:%s\n",__FUNCTION__);
}

/**
* @brief This function is a destructor of stater thread class used in the entTelematics process
*
* @return - none
*
* @note
*/
teleStarterThread::~teleStarterThread()
{
}

/**
* @brief This function retrieve the instance of the entTelematics starter thread
*
* @return
* created instance
*
* @note
*/
const teleStarterThread* teleStarterThread::getInstance()
{
    static teleStarterThread sInstance;
    return &sInstance;
}

/**
* @brief This function perform the instantiation of class.
*
* @return - none
*
* @note
*/
void teleStarterThread::instantiate() /*DG CPP2ISQP-ISQP Metric 3-SCC_GRANT_0008*/
{

  	LOG_PRINT(DPCA_TELE_MAIN_INFO,"[TELEMAIN]:%s\n",__FUNCTION__);

  	UMSGQ::getInstance().init(
		  entTlm_msg,
		  SIZE_OF_INFOTBL_ENTTELE,
		  "entTlmUMSGQThread");

   	/* set for the USMGQ is ready */

	/* read key from Reg, used for USB diag */
	readUsbParaFromReg();


  	/** read Persistent data if necessary


  	/** create new thread */
  	//start MQTT broker
  	//TODO: ADD CONDITION
  	teleATBCommAgent::startAgent();

  	//start Telematics main event thread
  	mpTlmBLthread = new teleMainBLThread(
	    ENTTELEMATICS_MAIN_BL_THREAD,
		ENTTELEMATICS_MAIN_BL_THREAD_PRORITY,
		ENTTELEMATICS_MAIN_BL_STACK_SIZE);

  	mpTlmAppthread = new teleMainAppThread(
	    ENTTELEMATICS_MAIN_APP_THREAD,
		ENTTELEMATICS_MAIN_APP_THREAD_PRORITY,
		ENTTELEMATICS_MAIN_APP_STACK_SIZE);

	// Create the thread to connection management
  	mpConnMgrBLThread = new ConnMgrBLThread(
		ENTTELEMATICS_CONNMGR_BL_THREAD,
		ENTTELEMATICS_CONNMGR_BL_THREAD_PRORITY,
		ENTTELEMATICS_CONNMGR_BL_STACK_SIZE);

	// Create the thread to remote configuration
  	mpRmtCfgSrvThread = new tlmRmtCfgSrvThread(
		ENTTELEMATICS_RMTCFG_BL_THREAD,
		ENTTELEMATICS_RMTCFG_BL_THREAD_PRORITY,
		ENTTELEMATICS_RMTCFG_BL_STACK_SIZE);

	// Create the thread to receive MOST message
    mpTlmMostReceiverThread = new Tlm_MostDispatcher_Thread(
        ENTTELEMATICS_MOST_RCVR_THREAD,
        ENTTELEMATICS_MOST_RCVR_THREAD_PRIORITY,
        ENTTELEMATICS_MOST_RCVR_STACK_SIZE);

	// Create the thread to usb diag
	if (1 == IsKitlEnable()) {
		// Create the thread to usb diag
		mpUsbDiagBLThread= new UsbDiagBLThread(
			  ENTTELEMATICS_USBDIAG_BL_THREAD,
			  ENTTELEMATICS_USBDIAG_BL_THREAD_PRIORITY,
			  ENTTELEMATICS_USBDIAG_BL_STACK_SIZE);

	} else {
		mpUsbDiagBLThread = 0;
	}

}


/**
* @brief This function handle the initialize of class.
*
* @return - none
*
*
* @note
*/
void teleStarterThread::initialize()
{

   LOG_PRINT(DPCA_TELE_MAIN_INFO,"[TELEMAIN]:%s\n",__FUNCTION__);

   // Async RPCs now use their own Zone Memory Allocator.
   bool_t result = InitializeRPCAsyncDescriptor();

   if(result == FALSE)
   {
      LOG_PRINT(DPCA_TELE_MAIN_ERROR,"[TELEMAIN]:%s-Init RPCAsync Failed\n",__FUNCTION__);
   }
}


/**
* @brief This function perform the termination of class during shutdown
*
* @return - none
*
* @note
*/
void teleStarterThread::terminate()
{

	//#[ operation terminate())
	LOG_PRINT(DPCA_TELE_MAIN_INFO,"[TELEMAIN]:%s\n",__FUNCTION__);
	UMSGQ::getInstance().destroyInstance();
	//#]

    if(NIL != mpTlmBLthread)
    {
        delete mpTlmBLthread;
        mpTlmBLthread = NIL;
    }

    if(NIL != mpTlmAppthread)
    {
        delete mpTlmAppthread;
        mpTlmAppthread = NIL;
    }

    if(NIL != mpTlmBLthread)
    {
        delete mpTlmBLthread;
        mpTlmBLthread = NIL;
    }

    if(NIL != mpConnMgrBLThread)
    {
        delete mpConnMgrBLThread;
        mpConnMgrBLThread = NIL;
    }

    if(NIL != mpRmtCfgSrvThread)
    {
        delete mpRmtCfgSrvThread;
        mpRmtCfgSrvThread = NIL;
    }

    if(NIL != mpRmtCfgSrvThread)
    {
        delete mpRmtCfgSrvThread;
        mpRmtCfgSrvThread = NIL;
    }

    if(NIL != mpTlmMostReceiverThread)
    {
        delete mpTlmMostReceiverThread;
        mpTlmMostReceiverThread = NIL;
    }

}


/**
*
* @brief This function notify the application process of the entTelematics is ready.
*        All the threads spawns in entTelematics process is ready for comunicating.
*
* @return - none
*
* @note
*/
void teleStarterThread::processReady(Thread* t)
{

  	LOG_PRINT(DPCA_TELE_MAIN_INFO,"[TELEMAIN]:%s\n",__FUNCTION__);

  	// Set the MOST function block is available
  	Tlm_MostStack *pMostStack = reinterpret_cast<Tlm_MostStack*>(&const_cast<Tlm_MostStack&>(Tlm_MostStack::getInstance()));
  	pMostStack->setAvailable(TRUE, miAudioLogicalSrc_FBlockID, miTlmAudioLogicalSrc_InstID);

	// Post event to initialize the entPushObjApp
	gTeleQueue.postEvent(EVT_PUSH_OBJECT_INITIALIZE, NIL);

	// Post event to initialize the entUrlBackApp
	gTeleQueue.postEvent(EVT_URL_BACK_INITIALIZE, NIL);

    // For test purpose
    gConnMgrQueue.postEvent(EVT_USB_CONN_STATUS, USB_STATE_CONNECTED);
	
	gTeleQueue.postEvent(EVT_RMTCFG_INIT, 1);
}


/**
 * @brief This function notify all the application processes is ready.
 *        The IPC communication of between the processes is allowed at this stage.
 *
 * @param [in] t
 * 	the calling thread
 *
 * @return
 *
 * @note
 */
void teleStarterThread::systemReady(Thread* t)
{
  LOG_PRINT(DPCA_TELE_MAIN_INFO,"[TELEMAIN]:%s\n",__FUNCTION__);

}


/**
 * @brief This function provide the interface for USB diag to get the mVBUSOnoff.
 *
 * @param [in] -none
 *
 * @return
 *	uint8_t value of "mVBUSOnoff".
 *			"0" or "1" - ranged values;
 *			"0xFF" - read Reg error;
 *
 * @note
 */
uint8_t teleStarterThread::GetUsbDiagEnable(void)
{
	return mVBUSOnoff;
}


/**
 * @brief This function provide the interface for USB diag to get the mVBUSPort.
 *
 * @param [in] - none
 *
 * @return
 *	uint8_t value of "mVBUSPort".
 *			"1" or "2" - ranged values;
 *			"0xFF" - read Reg error;
 *
 * @note
 */
uint8_t teleStarterThread::GetUsbDiagPort(void)
{
	return mVBUSPort;
}


/**
 * @brief This function read the keys from Register. The keys are used for USB diag.
 *
 * @param [in] -none
 *
 * @return - none
 *
 * @note
 */
void teleStarterThread::readUsbParaFromReg(void)
{
    HKEY hk = NIL;

    DWORD dwRV = RegOpenKeyEx (HKEY_LOCAL_MACHINE, L"Drivers\\BuiltIn\\TLM", 0, KEY_READ, reinterpret_cast<PHKEY>(&hk)); /*DG CPP2ISQP-ISQPcpp Rule 5.5.9-MMP_ExtGen_0001*/

    if (dwRV == ERROR_SUCCESS)
    {
        DWORD dwType = 0;
        DWORD dwData = 0;
        DWORD dwSize = sizeof(dwData);

        dwRV = RegQueryValueEx (hk, L"VBusOnOff", NIL, &dwType, reinterpret_cast<LPBYTE>(&dwData), &dwSize);

        if ((dwRV  == ERROR_SUCCESS))
        {
            mVBUSOnoff = dwData;
        }
        else{
			mVBUSOnoff = 0xFF;
		}

        dwData = 0;
        dwSize = sizeof(dwData);

        dwRV = RegQueryValueEx (hk, L"VBusPort", NIL, &dwType, reinterpret_cast<LPBYTE>(&dwData), &dwSize);

        if ((dwRV == ERROR_SUCCESS))
        {
            mVBUSPort = dwData;
        }
        else{
			mVBUSPort = 0xFF;
		}

        RegCloseKey (hk);
    }
	else{
		LOG_PRINT(DPCA_TELE_MAIN_INFO,"[TELEMAIN]:%s-open reg error!\n",__FUNCTION__);
	}

	LOG_PRINT(DPCA_TELE_MAIN_INFO,"[TELEMAIN]:%s(%d,%d)\n",__FUNCTION__,mVBUSOnoff,mVBUSPort);
}

uint8_t teleStarterThread::IsKitlEnable(void)
{
	DWORD retVal = 0;
	uint8_t  x = 0;
	uint32_t actualOut = 0;
	retVal = ssw_ergUserReadData(ERG_USER_SYSTEM, ERG_DPCA2_CONF_NAVI_MAPSCROLL, &x, sizeof(uint8_t), &actualOut);
	if(ER_ERG_SUCCESS == retVal)
	{
		LOG_PRINT(DPCA_TELE_MAIN_INFO,"[TELEMAIN]:%s-ERG_DPCA2_CONF_NAVI_MAPSCROLL %d\n",__FUNCTION__,x);
	}
	else
	{
	    LOG_PRINT(DPCA_TELE_MAIN_INFO,"[TELEMAIN]:%s-ERG_DPCA2_CONF_NAVI_MAPSCROLL FAIL!\n",__FUNCTION__);
	}
	return x;
}


